/*
cAndy Apple Core: An Apple //e emulator engine
    - based almost entirely on AppleWin

Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2008, Tom Charlesworth, Michael Pohoreski, Nick Westgate
Copyright (C) 2009-2010, Garnet Ulrich

cAndy Apple Core is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

cAndy Apple Core is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with cAndy Apple Core; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "wwrapper.h"
#include "StdAfx.h"

static BYTE DiskControlMotor (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE DiskControlStepper (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE DiskEnable (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE DiskReadWrite (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE DiskSetLatchValue (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE DiskSetReadMode (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE DiskSetWriteMode (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);

#define LOG_DISK_ENABLED 0

// Public _________________________________________________________________________________________

BOOL enhancedisk = 0;

char  diskimage0[232960];
char  diskimage1[232960];
BYTE  trackimage0[6656];
BYTE  trackimage1[6656];


static WORD		currdrive       = 0;
static BOOL		diskaccessed    = 0;
static Disk_t	g_aFloppyDisk[DRIVES];
static BYTE		floppylatch     = 0;
static BOOL		floppymotoron   = 0;
static BOOL		floppywritemode = 0;
static WORD		phases; // state bits for stepper magnet phases 0 - 3
static bool		bSaveDiskImage = true;

static void CheckSpinning();
static Disk_Status_e GetDriveLightStatus( const int iDrive );
static bool IsDriveValid( const int iDrive );
static void ReadTrack (int drive);
static void RemoveDisk (int drive);
static void WriteTrack (int drive);

unsigned char DISKROM[256] =
    {0xA2,0x20,0xA0,0x00,0xA2,0x03,0x86,0x3C,0x8A,0x0A,0x24,0x3C,0xF0,0x10,0x05,0x3C,
         0x49,0xFF,0x29,0x7E,0xB0,0x08,0x4A,0xD0,0xFB,0x98,0x9D,0x56,0x03,0xC8,0xE8,0x10,
         0xE5,0x20,0x58,0xFF,0xBA,0xBD,0x00,0x01,0x0A,0x0A,0x0A,0x0A,0x85,0x2B,0xAA,0xBD,
         0x8E,0xC0,0xBD,0x8C,0xC0,0xBD,0x8A,0xC0,0xBD,0x89,0xC0,0xA0,0x50,0xBD,0x80,0xC0,
         0x98,0x29,0x03,0x0A,0x05,0x2B,0xAA,0xBD,0x81,0xC0,0xA9,0x56,0xa9,0x00,0xea,0x88,
         0x10,0xEB,0x85,0x26,0x85,0x3D,0x85,0x41,0xA9,0x08,0x85,0x27,0x18,0x08,0xBD,0x8C,
         0xC0,0x10,0xFB,0x49,0xD5,0xD0,0xF7,0xBD,0x8C,0xC0,0x10,0xFB,0xC9,0xAA,0xD0,0xF3,
         0xEA,0xBD,0x8C,0xC0,0x10,0xFB,0xC9,0x96,0xF0,0x09,0x28,0x90,0xDF,0x49,0xAD,0xF0,
         0x25,0xD0,0xD9,0xA0,0x03,0x85,0x40,0xBD,0x8C,0xC0,0x10,0xFB,0x2A,0x85,0x3C,0xBD,
         0x8C,0xC0,0x10,0xFB,0x25,0x3C,0x88,0xD0,0xEC,0x28,0xC5,0x3D,0xD0,0xBE,0xA5,0x40,
         0xC5,0x41,0xD0,0xB8,0xB0,0xB7,0xA0,0x56,0x84,0x3C,0xBC,0x8C,0xC0,0x10,0xFB,0x59,
         0xD6,0x02,0xA4,0x3C,0x88,0x99,0x00,0x03,0xD0,0xEE,0x84,0x3C,0xBC,0x8C,0xC0,0x10,
         0xFB,0x59,0xD6,0x02,0xA4,0x3C,0x91,0x26,0xC8,0xD0,0xEF,0xBC,0x8C,0xC0,0x10,0xFB,
         0x59,0xD6,0x02,0xD0,0x87,0xA0,0x00,0xA2,0x56,0xCA,0x30,0xFB,0xB1,0x26,0x5E,0x00,
         0x03,0x2A,0x5E,0x00,0x03,0x2A,0x91,0x26,0xC8,0xD0,0xEE,0xE6,0x27,0xE6,0x3D,0xA5,
         0x3D,0xCD,0x00,0x08,0xA6,0x2B,0x90,0xDB,0x4C,0x01,0x08,0x00,0x00,0x00,0x00,0x00
    };

//===========================================================================
BOOL DiskActivity(int drive)
{
    return GetDriveLightStatus(drive);
}


//===========================================================================
void CheckSpinning () {
  DWORD modechange = (floppymotoron && !g_aFloppyDisk[currdrive].spinning);
  if (floppymotoron)
    g_aFloppyDisk[currdrive].spinning = 20000;
}

//===========================================================================
Disk_Status_e GetDriveLightStatus( const int iDrive )
{
    if (IsDriveValid( iDrive ))
    {
        Disk_t *pFloppy = & g_aFloppyDisk[ iDrive ];

        if (pFloppy->spinning)
        {
            if (pFloppy->writelight)
                return DISK_STATUS_WRITE;
            else
                return DISK_STATUS_READ;
        }
        else
            return DISK_STATUS_OFF;
    }

    return DISK_STATUS_OFF;
}


//===========================================================================
bool IsDriveValid( const int iDrive )
{
	if (iDrive < 0)
		return false;

	if (iDrive >= DRIVES)
		return false;

	return true;
}


//===========================================================================

static void AllocTrack(int drive)
{
  Disk_t * fptr = &g_aFloppyDisk[drive];
  if (drive == 0) {
      fptr->trackimage = &trackimage0[0];
  } else {
      fptr->trackimage = &trackimage1[0];
  }
}

//===========================================================================
static void ReadTrack (int iDrive)
{
	if (! IsDriveValid( iDrive ))
		return;

	Disk_t *pFloppy = &g_aFloppyDisk[iDrive];

	if (pFloppy->track >= ImageGetNumTracks(pFloppy))
	{
		pFloppy->trackimagedata = 0;
		return;
	}

	if (! pFloppy->trackimage)
		AllocTrack( iDrive );

	if (pFloppy->trackimage && pFloppy->diskindrive)
	{
		ImageReadTrack(pFloppy, &pFloppy->nibbles);
		pFloppy->byte           = 0;
		pFloppy->trackimagedata = (pFloppy->nibbles != 0);
	}
}

//===========================================================================
static void RemoveDisk (int iDrive)
{
	Disk_t *pFloppy = &g_aFloppyDisk[iDrive];

	if (pFloppy->diskindrive) //used to check imagehandle - must be to make sure that there is a valid diskette there - gu
	{
		if (pFloppy->trackimage && pFloppy->trackimagedirty) {
			WriteTrack( iDrive);
		}

		ImageClose(pFloppy); //we have nothing to close but need to free up memory

		pFloppy->diskindrive = false;
	}

	if (pFloppy->trackimage) {
	    pFloppy->trackimage     = NULL;
	    pFloppy->trackimagedata = 0;
	}
}

//===========================================================================
static void WriteTrack (int iDrive)
{
	Disk_t *pFloppy = &g_aFloppyDisk[ iDrive ];

	if (pFloppy->track >= ImageGetNumTracks(pFloppy))
		return;

	if (pFloppy->writeprotected)
		return;

	if (pFloppy->trackimage && pFloppy->diskindrive)
		ImageWriteTrack(pFloppy);

	pFloppy->trackimagedirty = 0;
}

//
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
//

//===========================================================================
void DiskBoot () {

    // THIS FUNCTION RELOADS A PROGRAM IMAGE IF ONE IS LOADED IN DRIVE ONE.
    // IF A DISK IMAGE OR NO IMAGE IS LOADED IN DRIVE ONE, IT DOES NOTHING.
    Disk_t * fptr = &g_aFloppyDisk[0];

    if (g_aFloppyDisk[0].diskindrive && ImageBoot(&g_aFloppyDisk[0])) //gu - converted check for imagehandle to diskindrive
        floppymotoron = 0;

}

//===========================================================================
static BYTE DiskControlMotor (WORD, WORD address, BYTE, BYTE, ULONG) {
    floppymotoron = address & 1;
    CheckSpinning();
    return MemReturnRandomData(1);
}

//===========================================================================
static BYTE DiskControlStepper (WORD, WORD address, BYTE, BYTE, ULONG)
{
    Disk_t * fptr = &g_aFloppyDisk[currdrive];
    int phase     = (address >> 1) & 3;
    int phase_bit = (1 << phase);

    // update the magnet states
    if (address & 1)
    {
        // phase on
        phases |= phase_bit;
    }
    else
    {
        // phase off
        phases &= ~phase_bit;
    }

    // check for any stepping effect from a magnet
    // - move only when the magnet opposite the cog is off
    // - move in the direction of an adjacent magnet if one is on
    // - do not move if both adjacent magnets are on
    // momentum and timing are not accounted for ... maybe one day!
    int direction = 0;
    if (phases & (1 << ((fptr->phase + 1) & 3)))
        direction += 1;
    if (phases & (1 << ((fptr->phase + 3) & 3)))
        direction -= 1;

    // apply magnet step, if any
    if (direction)
    {
        fptr->phase = MAX(0, MIN(79, fptr->phase + direction));
        const int nNumTracksInImage = ImageGetNumTracks(fptr);
        int newtrack = MIN(nNumTracksInImage-1, fptr->phase >> 1); // (round half tracks down)
        if (newtrack != fptr->track)
        {
            if (fptr->trackimage && fptr->trackimagedirty)
            {
                WriteTrack(currdrive);
            }
            fptr->track          = newtrack;
            fptr->trackimagedata = 0;
        }
    }
    return (address == 0xE0) ? 0xFF : MemReturnRandomData(1);
}

//===========================================================================
static BYTE DiskEnable (WORD, WORD address, BYTE, BYTE, ULONG) {
  currdrive = address & 1;
  g_aFloppyDisk[!currdrive].spinning   = 0;
  g_aFloppyDisk[!currdrive].writelight = 0;
  CheckSpinning();
  return 0;
}


//===========================================================================
void DiskEject( const int iDrive )
{
	if (IsDriveValid( iDrive ))
	{
		RemoveDisk( iDrive );
	}
}

//===========================================================================

static BYTE Disk_IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
static BYTE Disk_IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);

void CADiskSave (int iDrive, char* image, int disksize)  //only gets called by CACore.cpp jnisavedisk
{
    Disk_t *pFloppy = &g_aFloppyDisk[iDrive];

    if (pFloppy->trackimage && pFloppy->trackimagedirty) { //make sure that diskimageX is updated with changes to the track buffer
        WriteTrack(iDrive);
    }

    if (iDrive == 0) {
        memcpy(image,diskimage0,disksize);
    } else {
        memcpy(image,diskimage1,disksize);
    }
}
//===========================================================================

void CADiskLoadBytes (int iDrive, char* image, int disksize)  //only gets called by CACore.cpp jnisavedisk
{
    Disk_t *pFloppy = &g_aFloppyDisk[iDrive];

    if (iDrive == 0) {
        memcpy(diskimage0,image,disksize);
    } else {
        memcpy(diskimage1,image,disksize);
    }
}
//===========================================================================
int DiskInsert (int iDrive, char* image, int disksize, BOOL writeprotected, char* filename)  //only gets called by CACore.cpp jniloaddisk
{

	Disk_t * fptr = &g_aFloppyDisk[iDrive];


	if (fptr->diskindrive) {
		RemoveDisk(iDrive);
	}

	ZeroMemory(fptr,sizeof(Disk_t ));



	fptr->writeprotected = writeprotected;

	if (iDrive == 0) {
	    memcpy(diskimage0,image,disksize);
	    fptr->image = &diskimage0[0];
	} else {
	    memcpy(diskimage1,image,disksize);
	    fptr->image = &diskimage1[0];
	}

	fptr->disksize = disksize;
	fptr->diskindrive = true;

	int error = ImageOpen(filename, fptr);

	return error;
}

//===========================================================================
BOOL DiskIsSpinning ()
{
	return floppymotoron;
}

//===========================================================================
static BYTE DiskReadWrite (WORD programcounter, WORD, BYTE, BYTE, ULONG) {

  Disk_t * fptr = &g_aFloppyDisk[currdrive];
  diskaccessed = 1;

  if ((!fptr->trackimagedata) && fptr->diskindrive)
    ReadTrack(currdrive);

  if (!fptr->trackimagedata)
    return 0xFF;
  BYTE result = 0;
  if ((!floppywritemode) || (!fptr->writeprotected))
    if (floppywritemode)
      if (floppylatch & 0x80) {
        *(fptr->trackimage+fptr->byte) = floppylatch;
        fptr->trackimagedirty = 1;
      }
      else
        return 0;
    else
      result = *(fptr->trackimage+fptr->byte);

  if (++fptr->byte >= fptr->nibbles)
    fptr->byte = 0;
  return result;
}

//===========================================================================

void DiskReset()
{
	floppymotoron = 0;
	phases = 0;
}

//===========================================================================

static BYTE  DiskSetLatchValue (WORD, WORD, BYTE write, BYTE value, ULONG) {
  if (write)
    floppylatch = value;
  return floppylatch;
}

//===========================================================================
static BYTE  DiskSetReadMode (WORD, WORD, BYTE, BYTE, ULONG) {
  floppywritemode = 0;
  return MemReturnRandomData(g_aFloppyDisk[currdrive].writeprotected);
}

//===========================================================================
static BYTE  DiskSetWriteMode (WORD, WORD, BYTE, BYTE, ULONG) {
  floppywritemode = 1;
  BOOL modechange = !g_aFloppyDisk[currdrive].writelight;
  g_aFloppyDisk[currdrive].writelight = 20000;
  return MemReturnRandomData(1);
}

//===========================================================================
void DiskUpdatePosition (DWORD cycles) {
  int loop = 2;
  while (loop--) {
    Disk_t * fptr = &g_aFloppyDisk[loop];
    if (fptr->spinning && !floppymotoron) {
      if (!(fptr->spinning -= MIN(fptr->spinning,(cycles >> 6))))
          {}//FrameRefreshStatus(DRAW_LEDS);
    }
    if (floppywritemode && (currdrive == loop) && fptr->spinning)
      fptr->writelight = 20000;
    else if (fptr->writelight) {
      if (!(fptr->writelight -= MIN(fptr->writelight,(cycles >> 6))))
          {}//FrameRefreshStatus(DRAW_LEDS);
    }
    if ((!enhancedisk) && (!diskaccessed) && fptr->spinning) {
      //needsprecision = cumulativecycles; //gu - both variables look to be old garbage
      fptr->byte += (cycles >> 5);
      if (fptr->byte >= fptr->nibbles)
        fptr->byte -= fptr->nibbles;
    }
  }
  diskaccessed = 0;
}

//===========================================================================

// TODO: LoadRom_Disk_Floppy()
void DiskLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot)
{
	memcpy(pCxRomPeripheral + uSlot*APPLE_SLOT_SIZE, DISKROM, 0x0100); //copy in the rom from our embedded array

	// NB. We used to disable the track stepping delay in the Disk II controller firmware by
	// patching $C64C with $A9,$00,$EA. Now not doing this since:
	// . Authentic Speed should be authentic
	// . Enhanced Speed runs emulation unthrottled, so removing the delay has negligible effect
	// . Patching the firmware breaks the ADC checksum used by "The CIA Files" (Tricky Dick)
	// . In this case we can patch to compensate for an ADC or EOR checksum but not both

	RegisterIoHandler(uSlot, Disk_IORead, Disk_IOWrite, NULL, NULL, NULL, NULL);
}

//===========================================================================

static BYTE  Disk_IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft)
{

	addr &= 0xFF;

	switch (addr & 0xf)
	{
	case 0x0:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x1:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x2:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x3:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x4:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x5:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x6:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x7:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x8:	return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
	case 0x9:	return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
	case 0xA:	return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
	case 0xB:	return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
	case 0xC:	return DiskReadWrite(pc, addr, bWrite, d, nCyclesLeft);
	case 0xD:	return DiskSetLatchValue(pc, addr, bWrite, d, nCyclesLeft);
	case 0xE:	return DiskSetReadMode(pc, addr, bWrite, d, nCyclesLeft);
	case 0xF:	return DiskSetWriteMode(pc, addr, bWrite, d, nCyclesLeft);
	}

	return 0;
}

static BYTE  Disk_IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft)
{
	addr &= 0xFF;

	switch (addr & 0xf)
	{
	case 0x0:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x1:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x2:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x3:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x4:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x5:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x6:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x7:	return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
	case 0x8:	return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
	case 0x9:	return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
	case 0xA:	return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
	case 0xB:	return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
	case 0xC:	return DiskReadWrite(pc, addr, bWrite, d, nCyclesLeft);
	case 0xD:	return DiskSetLatchValue(pc, addr, bWrite, d, nCyclesLeft);
	case 0xE:	return DiskSetReadMode(pc, addr, bWrite, d, nCyclesLeft);
	case 0xF:	return DiskSetWriteMode(pc, addr, bWrite, d, nCyclesLeft);
	}

	return 0;
}

//===========================================================================

DWORD DiskGetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot) //for save state
{
    pSS->Hdr.UnitHdr.dwLength = sizeof(SS_CARD_DISK2);
    pSS->Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,2);

    pSS->Hdr.dwSlot = dwSlot;
    pSS->Hdr.dwType = CT_Disk2;
    pSS->phases             = phases; // new in 1.0.0.2 disk snapshots
    pSS->currdrive          = currdrive; // this was an int in 1.0.0.1 disk snapshots
    pSS->diskaccessed       = diskaccessed;
    pSS->enhancedisk        = enhancedisk;
    pSS->floppylatch        = floppylatch;
    pSS->floppymotoron      = floppymotoron;
    pSS->floppywritemode    = floppywritemode;
    pSS->g_uNumTracksInImage = g_uNumTracksInImage;
    for(UINT i=0; i<2; i++)
    {
        pSS->Unit[i].track              = g_aFloppyDisk[i].track;
        pSS->Unit[i].phase              = g_aFloppyDisk[i].phase;
        pSS->Unit[i].byte               = g_aFloppyDisk[i].byte;
        pSS->Unit[i].writeprotected     = g_aFloppyDisk[i].writeprotected;
        pSS->Unit[i].trackimagedata     = g_aFloppyDisk[i].trackimagedata;
        pSS->Unit[i].trackimagedirty    = g_aFloppyDisk[i].trackimagedirty;
        pSS->Unit[i].spinning           = g_aFloppyDisk[i].spinning;
        pSS->Unit[i].writelight         = g_aFloppyDisk[i].writelight;
        pSS->Unit[i].nibbles            = g_aFloppyDisk[i].nibbles;
        pSS->Unit[i].diskindrive        = g_aFloppyDisk[i].diskindrive;
        pSS->Unit[i].disksize           = g_aFloppyDisk[i].disksize;
        pSS->Unit[i].format             = g_aFloppyDisk[i].format;
        pSS->Unit[i].offset             = g_aFloppyDisk[i].offset;
        pSS->Unit[i].uNumTracks          = g_aFloppyDisk[i].uNumTracks;

        strcpy(pSS->Unit[i].filename,g_aFloppyDisk[i].filename);

        int foo;
        for (foo=0;foo<40;foo++) {  //gu - 40 tracks is MAX_TRACKS
            pSS->Unit[i].validtrack[foo] = g_aFloppyDisk[i].validtrack[foo];
        }

        if(g_aFloppyDisk[i].trackimage)
            memcpy(pSS->Unit[i].nTrack, g_aFloppyDisk[i].trackimage, NIBBLES_PER_TRACK);
        else
            memset(pSS->Unit[i].nTrack, 0, NIBBLES_PER_TRACK);
    }
    return 0;
}

DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/) //for load snapshot
{
    if(pSS->Hdr.UnitHdr.dwVersion > MAKE_VERSION(1,0,0,2)) {
        return -1;
    }

    phases          = pSS->phases; // new in 1.0.0.2 disk snapshots
    currdrive       = pSS->currdrive; // this was an int in 1.0.0.1 disk snapshots
    diskaccessed    = pSS->diskaccessed;
    enhancedisk     = pSS->enhancedisk;
    floppylatch     = pSS->floppylatch;
    floppymotoron   = pSS->floppymotoron;
    floppywritemode = pSS->floppywritemode;
    g_uNumTracksInImage = pSS->g_uNumTracksInImage;

    for(UINT i=0; i<2; i++) {
        ZeroMemory(&g_aFloppyDisk[i], sizeof(Disk_t ));

        Disk_t * fptr = &g_aFloppyDisk[0]; //fix the pointers we just zeroed out
        fptr->image = &diskimage0[0];
        fptr->trackimage = &trackimage0[0];
        Disk_t * fptr2 = &g_aFloppyDisk[1];
        fptr2->image = &diskimage1[0];
        fptr2->trackimage = &trackimage1[0];

        g_aFloppyDisk[i].track              = pSS->Unit[i].track;
        g_aFloppyDisk[i].phase              = pSS->Unit[i].phase;
        g_aFloppyDisk[i].byte               = pSS->Unit[i].byte;
        g_aFloppyDisk[i].writeprotected     = pSS->Unit[i].writeprotected;
        g_aFloppyDisk[i].trackimagedata     = pSS->Unit[i].trackimagedata;
        g_aFloppyDisk[i].trackimagedirty    = pSS->Unit[i].trackimagedirty;
        g_aFloppyDisk[i].spinning           = pSS->Unit[i].spinning;
        g_aFloppyDisk[i].writelight         = pSS->Unit[i].writelight;
        g_aFloppyDisk[i].nibbles            = pSS->Unit[i].nibbles;
        g_aFloppyDisk[i].diskindrive        = pSS->Unit[i].diskindrive;
        g_aFloppyDisk[i].disksize           = pSS->Unit[i].disksize;
        g_aFloppyDisk[i].format             = pSS->Unit[i].format;
        g_aFloppyDisk[i].offset             = pSS->Unit[i].offset;
        g_aFloppyDisk[i].uNumTracks         = pSS->Unit[i].uNumTracks ;

        strcpy(g_aFloppyDisk[i].filename, pSS->Unit[i].filename);

        int foo;
        for (foo=0;foo<40;foo++) {  //gu - 40 tracks is MAX_TRACKS
            g_aFloppyDisk[i].validtrack[foo] = pSS->Unit[i].validtrack[foo];
        }

        memcpy(g_aFloppyDisk[i].trackimage, pSS->Unit[i].nTrack, NIBBLES_PER_TRACK);
    }
    return 0;
}


